// JORGE FERNANDO GOMEZ
// 1259371
// 189631
// LEC A1
// MARTIN MÜLLER
// D02
// YANG LIU


#include <stdlib.h>
#include <stdio.h>

#include "figStack.h"
#include "util.h"

#line 6 "figStack.c"


/* initstack() allocates length times sizeof() Properties
 * struct to Figures->figProperties.  It initializes its
 * figure count and keeps track of the current stack size. */
void initstack ( FigStack * Figures, int length ) {

    Figures->figProperties = malloc(sizeof(struct Properties)*length);

    if ( !Figures->figProperties )
        kill( Figures, 0, __LINE__ );

    Figures->figureCount = 0;
    Figures->currSize = length;
}

/* addFig() stores localFigName in Figures with initfig().
 * if the current stack size is too small, addFig() calls
 * extendFigStack() to add more space. */
void addFig ( FigStack * Figures, char * localFigName ) {

    if ( Figures->figureCount == Figures->currSize )
        extendFigStack(Figures);

    initfig(Figures, localFigName);
}

/* initfig() takes a string figName and copies it into
 * Figures->figProperties[figIndex].figureName.
 * It sets its drawCount to 0 and sets isdefined to 1. */
void initfig ( FigStack * Figures, char * figName ) {

    int figIndex = Figures->figureCount;
    strncpy(Figures->figProperties[figIndex].figureName,
            figName, MAXLEN_FIG+1);

    Figures->figProperties[figIndex].dx = malloc(sizeof(double));
    Figures->figProperties[figIndex].dy = malloc(sizeof(double));

    Figures->figProperties[figIndex].drawCount = 0;
    Figures->figProperties[figIndex].isdefined = 1;
}

/* updatefig() updates information in Figures->figProperties
 * at index position with parameters found in string.
 * Integer type represents different types of parameters. */
void updatefig ( char * string, FigStack * Figures, int position, int type ) {

    int drawCount;
    double * doublesPair;

    /* Get parameters and store them accordingly. */
    if ( type == 2 ) {  /* FigStack definitions. */
        doublesPair = getDoubles(string, type, 2);
        Figures->figProperties[position].x = *doublesPair;
        Figures->figProperties[position].y = *(doublesPair+1);
    }
    else if ( type == 1 ) {     /* Draw commands. */
        doublesPair = getDoubles(string, type, 2);
        drawCount = Figures->figProperties[position].drawCount;
        Figures->figProperties[position].dx[drawCount] = *doublesPair;
        Figures->figProperties[position].dy[drawCount] = *(doublesPair+1);

        plusOneDraw(Figures, position);
        Figures->figProperties[position].drawCount++;
    }

    free(doublesPair);
}

/* plusOneDraw() allocates space for one more drawSegment for
 * the figure located at position inside the current Figures stack. */
void plusOneDraw(FigStack * Figures, int position) {

    Figures->figProperties[position].dx =
        realloc( Figures->figProperties[position].dx,
            sizeof(double) * (Figures->figProperties[position].drawCount + 2));

    Figures->figProperties[position].dy =
        realloc( Figures->figProperties[position].dy,
            sizeof(double) * (Figures->figProperties[position].drawCount + 2));

    if ( !(Figures->figProperties[position].dx) ||
         !(Figures->figProperties[position].dy) )

        kill( Figures, 1, __LINE__ );
}

/* getFigIndex() retrieves the index associated with nameString
 * inside Figures, and returns it.  Otherwise -1 is returned. */
int getFigIndex ( char * nameString, FigStack * Figures ) {

    int i;
    for ( i = 0; i < Figures->figureCount; i++ ) {
        if ( strncmp(nameString,
                    Figures->figProperties[i].figureName,
                    MAXLEN_FIG+1) == 0 ) {
            return i;
        }
    }

    return -1;
}

/* exists() looks for nameString inside Figures.
 * It returns 1 if nameString was found, or 0 otherwise. */
int figexists ( char * nameString, FigStack * Figures ) {

    int i;
    for ( i = 0; i < Figures->figureCount; i++ ) {

        if ( !(Figures->figProperties[i].isdefined) )
            continue;

        if (strncmp(nameString,
                    Figures->figProperties[i].figureName, MAXLEN_FIG+1) == 0 )
            return 1;

    }

    return 0;
}

/* clearfig() takes a position index in Figures->figProperties and resets
 * its deltas array to reset. */
void clearfig ( FigStack * Figures, int position, double resetvalue ) {

    int drawCount = Figures->figProperties[position].drawCount;

    memset(Figures->figProperties[position].dx,
            resetvalue, sizeof(double)*drawCount);

    memset(Figures->figProperties[position].dy,
            resetvalue, sizeof(double)*drawCount);

    Figures->figProperties[position].drawCount = 0;
}

/* extendFigStack() allocates space for more figure definitions in Figures. */
void extendFigStack ( FigStack * Figures  ) {

    Figures->figProperties = realloc(Figures->figProperties,
                                     sizeof(struct Properties) *
                                     Figures->currSize * 2 );

    if ( !(Figures->figProperties) )
        kill( Figures, 1, __LINE__ );

    Figures->currSize *= 2;
}

/* destroyFigStack() frees each of the deltas arrays at each
 * figProperties[] index, then frees figProperties array itself. */
void destroyFigStack ( FigStack * Figures ) {

    int i;
    int figureCount = Figures->figureCount;

    for ( i = 0; i < figureCount; i++ ) {
        free(Figures->figProperties[i].dx);
        free(Figures->figProperties[i].dy);
    }

    free(Figures->figProperties);
}
